package com.hooya.fa.eu.biz.service.impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateRange;
import cn.hutool.core.date.DateTime;
import com.alibaba.excel.EasyExcel;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.hooya.fa.eu.api.bo.OrderInfoBO;
import com.hooya.fa.eu.api.bo.TempMmjlBO;
import com.hooya.fa.eu.api.util.DateExtUtil;
import com.hooya.fa.eu.api.util.FileUtil;
import com.hooya.fa.eu.api.vo.OrderXsVO;
import com.hooya.fa.eu.api.vo.RateVO;
import com.hooya.fa.eu.api.vo.XsjlDeleteVO;
import com.hooya.fa.eu.biz.dao.entity.eu.his.*;
import com.hooya.fa.eu.biz.dao.manager.EuHisSaleManager;
import com.hooya.fa.eu.biz.dao.mapper.eu.his.*;
import com.hooya.fa.eu.biz.dao.mapper.stk.TempJcjlMapper;
import com.hooya.fa.eu.biz.dao.mapper.stk.TempXsjlMapper;
import com.hooya.fa.eu.biz.listener.*;
import com.hooya.fa.eu.biz.service.EuHistoryService;
import com.hooya.fa.eu.biz.service.OrderEuService;
import com.hooya.integrated.common.core.util.BeanCopyUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.hooya.fa.eu.api.constant.FileNameConstant.EU_HIS_FOLDER_NAME;
import static com.hooya.fa.eu.api.util.DateExtUtil.generateDateMonthRange;
import static com.hooya.fa.eu.api.util.DateExtUtil.getYesterday;

/**
 * @Description 1
 * @Author : Zongz
 * @Copyright Copyright (c) 豪雅集团
 * @Create 2024/3/19
 * @Version 1.0.0
 */
@Slf4j
@Service
@DS("fa_eu_his")
@AllArgsConstructor
public class EuHistoryServiceImpl implements EuHistoryService {

    private final static SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");

    private final EuHisSaleManager euHisSaleManager;

    private final HisTempJcjlMapper hisTempJcjlMapper;

    private final HisTempXsjlMapper hisTempXsjlMapper;

    private final HisTempKcjlDailyMapper hisTempKcjlDailyMapper;

    private final HisTempMmjlMapper hisTempMmjlMapper;

    private final HisTempPkpyMapper hisTempPkpyMapper;

    private final HisTempXsjlAbnormalMapper hisTempXsjlAbnormalMapper;

    private final HisTempXsjlDeleteMapper hisTempXsjlDeleteMapper;

    private final HisTempZyjlChangeMapper hisTempZyjlChangeMapper;

    private final HisTempZyjlDeleteMapper hisTempZyjlDeleteMapper;

    private final HisTempZyjlMapper hisTempZyjlMapper;

    private final TempJcjlMapper tempJcjlMapper;

    private final TempXsjlMapper tempXsjlMapper;

    private final OrderEuService orderEuService;

    private final static List<String> COMPANY = Arrays.asList("GLOBALWAY", "COSTWAY", "FDS",
            "COSTWAY-PL", "COSTWAY-IT", "COSTWAY-FR");

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void genEuHistoryData(String start, String end) {
        List<List<String>> dateRange;
        if (start.substring(0, 7).equals(end.substring(0, 7))) {
            dateRange = Collections.singletonList(Arrays.asList(start, end));
        } else {
            dateRange = generateDateMonthRange(start, end);
        }
        Map<String, String> useTime = new HashMap<>();
        List<TempKcjlDaily> kcList = new LinkedList<>();
        for (List<String> dateList : dateRange) {
            String startDate = dateList.get(0);
            String endDate = dateList.get(1);
            String key = "[" + startDate + "] - [" + endDate + "]";
            log.info(key);
            long s = System.currentTimeMillis();

            Map<String, List<TempJcjl>> jcMap = new HashMap<>();
            Map<String, List<TempZyjl>> zyMap = new HashMap<>();
            Map<String, List<TempPkpy>> pkpyMap = new HashMap<>();
            Map<String, List<TempMmjl>> mmMap = new HashMap<>();
            Map<String, List<TempXsjl>> xsMap = new HashMap<>();
            //结束仓库(用于校队)
            List<TempKcjlDaily> kcEndList = new LinkedList<>();
            if (start.equals(startDate)) {
                readAndInsert(null, null, null, null, null, kcList, startDate);
            }
            readAndInsert(jcMap, zyMap, pkpyMap, mmMap, xsMap, kcEndList, endDate);
            //进行仓库记录的扣减逻辑
            Date curMon = new Date(startDate.replace("-", "/"));
            Date nextMon = new Date(endDate.replace("-", "/"));
            DateRange dayRange = DateExtUtil.range(curMon, nextMon, DateField.DAY_OF_MONTH);
            for (DateTime date : dayRange) {
                String curDay = date.toDateStr();
                //进仓
                List<TempJcjl> curJcList = jcMap.get(curDay);
                if (!CollectionUtils.isEmpty(curJcList)) {
                    for (TempJcjl jc : curJcList) {
                        dealKc(kcList, jc.getCpbh(), jc.getPlace(), jc.getBelongs(), jc.getSl(), curDay);
                    }
                }
                //转运+
                List<TempZyjl> curZyList = zyMap.get(curDay);
                if (!CollectionUtils.isEmpty(curZyList)) {
                    for (TempZyjl zy : curZyList) {
                        dealKc(kcList, zy.getCpbh(), zy.getZlck(), zy.getFromBelongs(), zy.getSl(), curDay);
                    }
                }
                //买卖+
                List<TempMmjl> curMmList = mmMap.get(curDay);
                if (!CollectionUtils.isEmpty(curMmList)) {
                    for (TempMmjl mm : curMmList) {
                        if (COMPANY.contains(mm.getToCompany())) {
                            dealKc(kcList, mm.getCpbh(), mm.getPlace(), mm.getToCompany(), mm.getSl(), curDay);
                        }
                    }
                }
                //pkpy
                List<TempPkpy> curPkpyList = pkpyMap.get(curDay);
                if (!CollectionUtils.isEmpty(curPkpyList)) {
                    for (TempPkpy pkpy : curPkpyList) {
                        dealKc(kcList, pkpy.getCpbh(), pkpy.getPlace(), pkpy.getBelongs(), -pkpy.getSl(), curDay);
                    }
                }
                //转运-
                if (!CollectionUtils.isEmpty(curZyList)) {
                    for (TempZyjl zy : curZyList) {
                        dealKc(kcList, zy.getCpbh(), zy.getZcck(), zy.getFromBelongs(), -zy.getSl(), curDay);
                    }
                }
                //买卖-
                if (!CollectionUtils.isEmpty(curMmList)) {
                    for (TempMmjl mm : curMmList) {
                        dealKc(kcList, mm.getCpbh(), mm.getPlace(), mm.getFromCompany().toUpperCase(),
                                -mm.getSl(), curDay);
                    }
                }
                //销售-
                List<TempXsjl> curXsList = xsMap.get(curDay);
                if (!CollectionUtils.isEmpty(curXsList)) {
                    for (TempXsjl xs : curXsList) {
                        dealKc(kcList, xs.getCpbh(), xs.getChck(), xs.getCompany().toUpperCase(),
                                -xs.getSl(), curDay);
                    }
                }
                //新增正常数据（除最后一天之外）
                if (!curDay.equals(endDate)) {
                    String yesterday = getYesterday(endDate);
                    if (yesterday.equals(curDay)) {
                        //买卖数据的GLOBALWAY特殊情况,放到最后一日处理
                        List<TempMmjl> nullDateMmList = mmMap.get("");
                        if (!CollectionUtils.isEmpty(nullDateMmList)) {
                            for (TempMmjl mm : nullDateMmList) {
                                if (mm.getFromCompany().equals("GLOBALWAY")) {
                                    dealKc(kcList, mm.getCpbh(), mm.getPlace(), mm.getToCompany().toUpperCase(),
                                            mm.getSl(), yesterday);
                                    dealKc(kcList, mm.getCpbh(), mm.getPlace(), mm.getFromCompany().toUpperCase(),
                                            -mm.getSl(), yesterday);
                                } else {
                                    log.info("买卖数据：" + mm);
                                }
                            }
                        }
                    }
                    List<TempKcjlDaily> addKcList = kcList.stream().filter(l -> l.getSl() != 0).collect(Collectors.toList());
                    addKc(addKcList, curDay);
                }
            }

            kcList = kcList.stream().filter(l -> l.getSl() != 0).collect(Collectors.toList());
            //与 kcEndList 做对比
            kcList.forEach(l -> {
                l.setId(null);
                l.setCreateTime(null);
            });
            if (kcEndList.size() != kcList.size()) {
                if (kcList.size() > kcEndList.size()) {
                    kcList.removeAll(kcEndList);
                }
                throw new RuntimeException("[" + startDate.substring(0, 7) + "]数据不对等，请核对！");
            }
            kcEndList.removeAll(kcList);
            if (kcEndList.size() != 0) {
                throw new RuntimeException("[" + startDate.substring(0, 7) + "]数据有误，请核对！");
            }

            String value = "用时为：" + (System.currentTimeMillis() - s) + "ms";
            log.info(value);
            useTime.put(key, value);
        }
        System.out.println(useTime);
    }

    public void addKc(List<TempKcjlDaily> addKcList, String curDay) {
        Date createTime = new Date();
        addKcList.forEach(l -> {
            l.setDate(curDay);
            l.setId(null);
            l.setCreateTime(createTime);
        });
        //分段新增，提升效率
        int partialLimit = addKcList.size() / 300 + 1;
        if (partialLimit > 1) {
            int limit = (addKcList.size() + partialLimit - 1) / partialLimit;
            List<List<TempKcjlDaily>> splitList = Stream.iterate(0, n -> n + 1)
                    .limit(partialLimit).parallel()
                    .map(a -> addKcList.stream().skip((long) a * limit).limit(limit)
                            .parallel().collect(Collectors.toList())).collect(Collectors.toList());
            for (int i = 0; i < splitList.size(); i++) {
                hisTempKcjlDailyMapper.insertBatchSomeColumn(splitList.get(i));
            }
        }
    }

    //处理库存
    private void dealKc(List<TempKcjlDaily> kcList, String cpbh, String place, String belongs,
                        int sl, String curDay) {
        if (kcList.stream().anyMatch(l -> l.getCpbh().equals(cpbh) &&
                l.getPlace().equals(place) && l.getBelongs().equals(belongs))) {
            kcList.stream().filter(l -> l.getCpbh().equals(cpbh) &&
                            l.getPlace().equals(place) && l.getBelongs().equals(belongs))
                    .forEach(l -> l.setSl(l.getSl() + sl));
        } else {
            TempKcjlDaily kc = TempKcjlDaily.builder().cpbh(cpbh).place(place)
                    .sl(sl).belongs(belongs).date(curDay).build();
            kcList.add(kc);
        }
    }

    //读取并新增excel的数据
    public void readAndInsert(Map<String, List<TempJcjl>> jcMap, Map<String, List<TempZyjl>> zyMap,
                              Map<String, List<TempPkpy>> pkpyMap, Map<String, List<TempMmjl>> mmMap,
                              Map<String, List<TempXsjl>> xsMap, List<TempKcjlDaily> kcList, String date) {
        String fileName = "result" + date + ".xlsx";
        String path = FileUtil.getExcelPath() + EU_HIS_FOLDER_NAME + fileName;
        //进仓数据
        List<TempJcjl> newJcjl = EasyExcel.read(path, TempJcjl.class,
                new JcHisListener(hisTempJcjlMapper)).sheet("newJcjl").doReadSync();
        if (!CollectionUtils.isEmpty(newJcjl) && jcMap != null) {
            jcMap.putAll(newJcjl.stream().collect(Collectors.groupingBy(TempJcjl::getHtrq)));
        }
        //转运数据
        List<TempZyjl> newZyjl = EasyExcel.read(path, TempZyjl.class,
                new ZyHisListener(hisTempZyjlMapper)).sheet("newZyjl").doReadSync();
        if (!CollectionUtils.isEmpty(newZyjl) && zyMap != null) {
            zyMap.putAll(newZyjl.stream().collect(Collectors.groupingBy(TempZyjl::getHtrq)));
        }
        //zyjlDelete数据
        EasyExcel.read(path, TempZyjlDelete.class,
                new ZyDeleteHisListener(hisTempZyjlDeleteMapper)).sheet("zyjlDelete").doRead();
        //zyjlChange数据
        EasyExcel.read(path, TempZyjlChange.class,
                new ZyChangeHisListener(hisTempZyjlChangeMapper)).sheet("changeZyDataAll").doRead();
        //xsjlDelete数据
        EasyExcel.read(path, TempXsjlDelete.class,
                new XsDeleteHisListener(hisTempXsjlDeleteMapper)).sheet("xsjlDelete").doRead();
        //盘亏盘盈数据
        List<TempPkpy> pkpyData = EasyExcel.read(path, TempPkpy.class,
                new PkpyHisListener(hisTempPkpyMapper)).sheet("pkpyData").doReadSync();
        if (!CollectionUtils.isEmpty(pkpyData) && pkpyMap != null) {
            pkpyMap.putAll(pkpyData.stream().collect(Collectors.groupingBy(TempPkpy::getDate)));
        }
        //买卖数据
        List<TempMmjl> mmData = EasyExcel.read(path, TempMmjl.class,
                new MmHisListener(hisTempMmjlMapper)).sheet("mmData").doReadSync();
        if (!CollectionUtils.isEmpty(mmData) && mmMap != null) {
            mmData.forEach(l -> {
                if (StringUtils.isBlank(l.getDate())) {
                    l.setDate("");
                }
                l.setToCompany(l.getToCompany().toUpperCase());
                l.setFromCompany(l.getFromCompany().toUpperCase());
            });
            mmMap.putAll(mmData.stream().collect(Collectors.groupingBy(TempMmjl::getDate)));
        }

        //销售记录做处理
        List<TempXsjl> newXsjlData = EasyExcel.read(path, TempXsjl.class,
                new XsHisListener(hisTempXsjlMapper)).sheet("newXsjlData").doReadSync();
        if (!CollectionUtils.isEmpty(newXsjlData) && xsMap != null) {
            List<XsjlDeleteVO> deleteList = new ArrayList<>();
            List<XsjlDeleteVO> xsjlDeleteList = EasyExcel.read(path).head(XsjlDeleteVO.class)
                    .sheet("xsjlDelete").doReadSync();
            List<XsjlDeleteVO> abnormalXsjlList = EasyExcel.read(path).head(XsjlDeleteVO.class)
                    .sheet("abnormalXsjl").doReadSync();
            if (!CollectionUtils.isEmpty(xsjlDeleteList)) {
                deleteList.addAll(xsjlDeleteList);
            }
            if (!CollectionUtils.isEmpty(abnormalXsjlList)) {
                deleteList.addAll(abnormalXsjlList);
            }
            if (!CollectionUtils.isEmpty(deleteList)) {
                List<String> sheetNumberList = deleteList.stream()
                        .map(XsjlDeleteVO::getSheetNumber).collect(Collectors.toList());
                List<TempXsjl> xsjlSheetNumber = newXsjlData.stream().filter(l -> !sheetNumberList.contains(l.getSheetNumber()))
                        .collect(Collectors.toList());
                if (xsjlSheetNumber.size() != newXsjlData.size()) {
                    newXsjlData.removeAll(xsjlSheetNumber);
                    throw new RuntimeException("销售被删除：" + newXsjlData);
                }
            }
            newXsjlData.forEach(l -> l.setCompany(l.getCompany().toUpperCase()));
            xsMap.putAll(newXsjlData.stream().filter(l -> COMPANY.contains(l.getCompany().toUpperCase()))
                    .collect(Collectors.groupingBy(TempXsjl::getOrderDate)));
        }
        //仓库数据
        List<TempKcjlDaily> kcjlData = EasyExcel.read(path).head(TempKcjlDaily.class)
                .sheet("kcjlData").doReadSync();
        if (!CollectionUtils.isEmpty(kcjlData) && kcList != null) {
            String yesterday = getYesterday(date);
            kcjlData.forEach(l -> l.setDate(yesterday));
            kcList.addAll(kcjlData);
        }
        //xsjlAbnormal入库
        EasyExcel.read(path, TempXsjlAbnormal.class,
                new XsAbnormalHisListener(hisTempXsjlAbnormalMapper)).sheet("abnormalXsjl").doRead();
    }

    @Override
    public void appendMmjl() {
        String path = FileUtil.getExcelPath() + EU_HIS_FOLDER_NAME + "fds/";
        List<String> fileNameList = FileUtil.getFileNamesByPath(path);
        List<TempMmjl> allRestockData = new LinkedList<>();
        Date date = new Date();
        for (String fileName : fileNameList) {
            List<TempMmjl> restock = EasyExcel.read(path + fileName)
                    .head(TempMmjl.class).sheet("restockMm").doReadSync();
            if (!CollectionUtils.isEmpty(restock)) {
                restock.forEach(l -> l.setCreateTime(date));
                allRestockData.addAll(restock);
            }
        }
        hisTempMmjlMapper.insertBatchSomeColumn(allRestockData);
    }

    @Override
    public void getOrderBelongs() {
        //获取19-20年的数据
        String fileName = "19-20.xls";
        String path = FileUtil.getExcelPath() + EU_HIS_FOLDER_NAME + fileName;
        List<OrderInfoBO> plFds = EasyExcel.read(path).head(OrderInfoBO.class).sheet("Polen").doReadSync();
        //合同号
        List<String> invoiceNoList = plFds.stream().map(OrderInfoBO::getInvoiceNo).collect(Collectors.toList());
        //进仓记录
        List<TempJcjl> tempJcjlList = hisTempJcjlMapper.getListByHthm(invoiceNoList);
        Map<String, List<TempJcjl>> jcMap = tempJcjlList.stream().collect(Collectors.groupingBy(TempJcjl::getHthm));
        Set<String> cpbhs = tempJcjlList.stream().map(TempJcjl::getCpbh).collect(Collectors.toSet());
        //（符合减扣）销售数据
        List<OrderXsVO> orderXsList = hisTempXsjlMapper.getOrderXsListBySkuList(cpbhs);
        //跳过备忘录
        List<String> continueMemo = new ArrayList<>();
        //销售结果
        List<OrderXsVO> orderXsRes = new LinkedList<>();
        Map<String, List<TempJcjl>> sortJcMap = new TreeMap<>(jcMap);
        sortJcMap.forEach((invoiceNo, jcList) -> {
            for (TempJcjl jc : jcList) {
                if (!CollectionUtils.isEmpty(continueMemo)) {
                    if (continueMemo.contains(jc.getCpbh() + jc.getPlace())) {
                        continue;
                    }
                }
                //初始值，找到进仓数量的所有买卖与销售
                Integer jcSl = jc.getSl();
                List<OrderXsVO> xsList = orderXsList.stream().filter(l -> l.getCpbh().equals(jc.getCpbh()) &&
                        l.getChck().equals(jc.getPlace())).filter(l -> {
                    try {
                        long orderTime = df.parse(l.getOrderDate()).getTime();
                        long htTime = df.parse(jc.getHtrq()).getTime();
                        if (orderTime >= htTime) {
                            return true;
                        }
                    } catch (Exception e) {
                        throw new RuntimeException(e.getMessage());
                    }
                    return false;
                }).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(xsList)) {
                    int xsSl = xsList.stream().mapToInt(OrderXsVO::getSl).sum();
                    int num = jcSl - xsSl;
                    //销售数据取多少数量
                    int sellNum = num >= 0 ? xsSl : jcSl;
                    //全部被卖
                    if (num >= 0) {
                        //截止23.03所有销售数据被卖，后续碰到改产品编号可直接跳过
                        continueMemo.add(jc.getCpbh() + jc.getPlace());
                        orderXsList.removeAll(xsList);
                        xsList.forEach(l -> l.setInvoiceNo(invoiceNo));
                        orderXsRes.addAll(xsList);
                        continue;
                    }
                    //没有被卖完的情况(存在拆单情况，即卖出2个，但是只需要一个，只需要改变原始数据的数量，并且orderXsList不需要remove)
                    dealNotSoldOut(invoiceNo, sellNum, xsList, orderXsList, orderXsRes);
                }
            }
        });
        if (!CollectionUtils.isEmpty(orderXsRes)) {
            EasyExcel.write(FileUtil.getExcelPath() + "pl-fds-2303.xlsx", OrderXsVO.class)
                    .sheet("order").doWrite(orderXsRes);
        }
    }

    private void dealNotSoldOut(String invoiceNo, int sellNum, List<OrderXsVO> xsList,
                                List<OrderXsVO> orderXsList, List<OrderXsVO> orderXsRes) {
        for (OrderXsVO xs : xsList) {
            int residue = sellNum - xs.getSl();
            if (residue >= 0) {
                orderXsList.remove(xs);
                xs.setInvoiceNo(invoiceNo);
                orderXsRes.add(xs);
                if (residue == 0) {
                    break;
                }
            } else {
                orderXsList.stream().filter(l -> Objects.equals(l, xs)).forEach(l -> l.setSl(Math.abs(residue)));
                xs.setSl(sellNum);
                orderXsRes.add(xs);
                break;
            }
            sellNum = residue;
        }
    }

    @Override
    public void editOrderExcel() {
        String rateFileName = "rate.csv";
        String orderFileName = "PL-FDS汇总.xlsx";
        String ratePath = FileUtil.getExcelPath() + EU_HIS_FOLDER_NAME + rateFileName;
        String orderPath = FileUtil.getExcelPath() + orderFileName;
        //rate
        List<RateVO> rateList = EasyExcel.read(ratePath).head(RateVO.class).sheet().doReadSync();
        Map<String, String> rateMap = rateList.stream().collect(Collectors.toMap(RateVO::getCountry, RateVO::getRate));
        //read order
        List<OrderXsVO> orderList = EasyExcel.read(orderPath).head(OrderXsVO.class).sheet("order").doReadSync();
        //add LogisticsId
        Set<String> sheetNumberList = orderList.stream().map(OrderXsVO::getSheetNumber).collect(Collectors.toSet());
        Set<String> halfSet = sheetNumberList.stream().skip(sheetNumberList.size() / 4)
                .limit(sheetNumberList.size() / 2).collect(Collectors.toSet());
        sheetNumberList.removeAll(halfSet);
        Map<String, String> LogisticsWay1Map = orderEuService.getLogisticsWayMapBySheetNumber(sheetNumberList);
        Map<String, String> LogisticsWay2Map = orderEuService.getLogisticsWayMapBySheetNumber(halfSet);
        //赋值
        orderList.forEach(l -> {
            String logisticsWay;
            l.setRate(rateMap.get(l.getToCountry()) + "%");
            logisticsWay = LogisticsWay1Map.get(l.getSheetNumber());
            if (StringUtils.isNotBlank(logisticsWay)) {
                l.setLogisticsId(logisticsWay);
            }
            logisticsWay = LogisticsWay2Map.get(l.getSheetNumber());
            if (StringUtils.isNotBlank(logisticsWay)) {
                l.setLogisticsId(logisticsWay);
            }
        });


        //write order
        EasyExcel.write(FileUtil.getExcelPath() + "pl-fds-2303.xlsx", OrderXsVO.class)
                .sheet("order").doWrite(orderList);
    }

    @Override
    public void genSellReport(String startDate, String endDate, boolean his, boolean sale) {
        List<TempJcjl> jcjlList = new ArrayList<>();
        List<TempXsjl> xsjlList = new ArrayList<>();
        List<TempKcjlDaily> kcjlList = new ArrayList<>();
        List<TempPkpy> pyList = new ArrayList<>();
        List<TempZyjl> zyList = new ArrayList<>();
        List<TempMmjlBO> mmList = new ArrayList<>();

        String yesterday = getYesterday(startDate);
        //本地出具的发票号信息
        Map<Integer, String> invoiceNoList = new HashMap<>();

        if (his) {
            //将date前同一天所有sku的数量加一起的进仓数据
            jcjlList = hisTempJcjlMapper.getGroupListByDate(endDate);
            //库存数据（和jcjlList有重合，库存数据会多一些转运数据【即没有发票号】）
            kcjlList = hisTempKcjlDailyMapper.getListByDate(yesterday);
            //盘盈
            pyList = hisTempPkpyMapper.getPyListByDate(startDate, endDate);
            //所有转运数据
            zyList = hisTempZyjlMapper.getListByDate(startDate, endDate);
            if (sale) {
                //所有的销售数据
                xsjlList = hisTempXsjlMapper.getListByDate(startDate, endDate);
            } else {
                //所有买卖
                mmList = hisTempMmjlMapper.getListByDate(startDate, endDate);
                //出具的发票号
                invoiceNoList = mmList.stream().collect(Collectors.toMap(TempMmjlBO::getId, TempMmjlBO::getInvoiceNo));
            }

        } else {
//            jcjlList = new ArrayList<>();
            //todo 需改逻辑（与历史一样）
            List<com.hooya.fa.eu.biz.dao.entity.TempJcjl> jcList = tempJcjlMapper.getGroupListByDate(endDate);
            jcjlList.addAll(BeanCopyUtils.copyListProperties(jcList, TempJcjl::new, (s, t) -> t.setSl(s.getCgsl())));
            List<com.hooya.fa.eu.biz.dao.entity.TempXsjl> xsList = tempXsjlMapper.getListByDate(startDate, endDate);
            xsjlList.addAll(
                    BeanCopyUtils.copyListProperties(xsList, TempXsjl::new, (s, t) -> t.setKhName(s.getKhname())));
        }
        List<TempJcjl> finalJcList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(jcjlList) && !CollectionUtils.isEmpty(kcjlList)) {
            Map<String, TempKcjlDaily> kcMap = kcjlList.stream()
                    .collect(Collectors.toMap(l -> l.getCpbh() + l.getPlace() + l.getBelongs(), i -> i));
            Map<String, List<TempJcjl>> jcMap = jcjlList.stream()
                    .filter(l -> (StringUtils.isNotBlank(l.getHtrq()) && StringUtils.compare(startDate, l.getHtrq()) > 0))
                    .collect(Collectors.groupingBy(l -> l.getCpbh() + l.getPlace() + l.getBelongs()));
            List<TempJcjl> kcToJc = new ArrayList<>();
            kcMap.forEach((key, kc) -> {
                List<TempJcjl> list = jcMap.get(key);
                // 进仓里没有库存相关的数据，表示库存里都是转运来的,即原始库存
                if (CollectionUtils.isEmpty(list)) {
                    kcToJc.add(BeanCopyUtils.copyPropertiesNew(kc, TempJcjl::new, (s, t) -> t.setHtrq(yesterday)));
                } else {
                    int jcTotal = list.stream().mapToInt(TempJcjl::getSl).sum();
                    if (jcTotal == kc.getSl()) {
                        kcToJc.addAll(list);
                        return;
                    }
                    // 进仓的数量多，我们可以理解为库存的数据只有进仓这一种类型（之前卖掉的都是进仓或者转运），以实际库存为准
                    if (jcTotal > kc.getSl()) {
                        int kcSl = kc.getSl();
                        for (TempJcjl jc : list) {
                            if (kcSl > 0) {
                                if (kcSl - jc.getSl() < 0) {
                                    jc.setSl(kcSl);
                                    finalJcList.add(jc);
                                } else {
                                    finalJcList.add(jc);
                                }
                            }
                            kcSl = Math.max(kcSl - jc.getSl(), 0);
                        }
                        if (kcSl > 0) {
                            log.info("逻辑有问题，数量还剩余" + kcSl);
                        }
                    }
                    // 库存的数量多，表示除了进仓之外可能还有转运，但转运是没有清关发票，所以在最终的进仓记录里要加上转运的sku
                    if (jcTotal < kc.getSl()) {
                        finalJcList.addAll(list);
                        kcToJc.add(BeanCopyUtils.copyPropertiesNew(kc, TempJcjl::new,
                                (s, t) -> {
                                    t.setSl(kc.getSl() - jcTotal);
                                    t.setHtrq(yesterday);
                                }));
                    }
                }
            });
            finalJcList.addAll(kcToJc);
        } else {
            finalJcList.addAll(jcjlList);
        }
        //初始化数量
        Map<String, List<TempJcjl>> initJcMap = finalJcList.stream()
                .filter(l -> (StringUtils.isNotBlank(l.getHtrq()) && StringUtils.compare(startDate, l.getHtrq()) > 0)
                        || StringUtils.isBlank(startDate))
                .collect(Collectors.groupingBy(l -> l.getCpbh() + l.getPlace()));
        Map<String, List<TempXsjl>> xsDateMap = xsjlList.stream().collect(Collectors.groupingBy(TempXsjl::getOrderDate));


        if (!sale) {
            //买卖
            List<TempXsjl> tempXsjls = BeanCopyUtils.copyListProperties(mmList, TempXsjl::new, (s, t) -> {
                t.setOrderDate(s.getDate());
                t.setChck(s.getPlace());
                t.setCompany(s.getToCompany());
                t.setBelongs(s.getFromCompany());
            });
            xsDateMap = tempXsjls.stream().collect(Collectors.groupingBy(TempXsjl::getOrderDate));
        }


        //处理生成每月数据
        List<List<String>> monthList = generateDateMonthRange(startDate, endDate);
        for (List<String> monthDay : monthList) {
            euHisSaleManager.genMonthSaleReport(monthDay.get(0), monthDay.get(1), jcjlList,
                    initJcMap, xsDateMap, zyList, pyList, invoiceNoList);
        }
    }

}
